#include "nolock_list.h"

SPSCLockFreeListQueue *spsc_list_queue_init()
{
    SPSCLockFreeListQueue *queue = (SPSCLockFreeListQueue *)kvs_malloc(sizeof(SPSCLockFreeListQueue));
    if (!queue)
        return NULL;

    // 创建哨兵节点（环形初始化：next指向自身）
    queue->sentinel = (NOLOCK_Node *)kvs_malloc(sizeof(NOLOCK_Node));
    if (!queue->sentinel)
    {
        kvs_free(queue);
        return NULL;
    }
    queue->sentinel->data = NULL;
    queue->sentinel->next = queue->sentinel; // 初始环

    // 初始化head和tail，均指向哨兵节点；任务计数初始为0
    atomic_store(&queue->head, queue->sentinel);
    atomic_store(&queue->tail, queue->sentinel);
    atomic_store(&queue->task_count, 0); // 初始化任务数为0

    return queue;
}
// 入队时任务计数+1
int spsc_list_queue_enqueue(SPSCLockFreeListQueue *queue, void *data)
{
    if (!queue || !data)
        return -1;

    NOLOCK_Node *new_node = (NOLOCK_Node *)kvs_malloc(sizeof(NOLOCK_Node));
    if (!new_node)
        return -1;
    new_node->data = data;
    new_node->next = queue->sentinel;

    NOLOCK_Node *old_tail = atomic_load(&queue->tail);
    old_tail->next = new_node;
    atomic_store(&queue->tail, new_node);

    // 关键：入队后任务计数+1
    atomic_fetch_add(&queue->task_count, 1);
    return 0;
}

// 出队时任务计数-1
void *spsc_list_queue_dequeue(SPSCLockFreeListQueue *queue)
{
    if (!queue)
        return NULL;

    NOLOCK_Node *head = atomic_load(&queue->head);
    NOLOCK_Node *next_node = head->next;

    if (next_node == queue->sentinel)
    {
        return NULL;
    }

    void *data = next_node->data;
    atomic_store(&queue->head, next_node);
    if (head != queue->sentinel)
    {
         kvs_free(head);
    }
   

    // 关键：出队后任务计数-1
    atomic_fetch_sub(&queue->task_count, 1);
    return data;
}

void spsc_list_queue_destroy(SPSCLockFreeListQueue *queue)
{
    if (!queue)
        return;

    // 释放剩余节点
    NOLOCK_Node *current = atomic_load(&queue->head);

    while (current != queue->sentinel)
    {
        NOLOCK_Node *next = current->next;
        //kvs_free(current->data); // 假设数据由用户分配，需释放, 由用户释放
        kvs_free(current);
        current = next;
    }
    // 释放哨兵节点和队列本身
    kvs_free(queue->sentinel);
    kvs_free(queue);
}
